
<!DOCTYPE html>
<html lang="zh-cn" itemscope itemtype="http://schema.org/WebPage">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Go 每日一库之 go-flags - 大俊的博客</title>


    <meta name="renderer" content="webkit" />
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes"/>

    <meta name="MobileOptimized" content="width"/>
    <meta name="HandheldFriendly" content="true"/>


    <meta name="applicable-device" content="pc,mobile">

    <meta name="theme-color" content="#f8f5ec" />
    <meta name="msapplication-navbutton-color" content="#f8f5ec">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">

    <meta name="mobile-web-app-capable" content="yes">

    <meta name="author" content="darjun" />
    <meta name="description" content="简介 在上一篇文章中，我们介绍了flag库。flag库是用于解析命令行选项的。但是flag有几个缺点： 不显示支持短选项。当然上一篇文章中也提到" />

    <meta name="keywords" content="大俊, 大俊的博客, go, golang, gopher" />






    <meta name="generator" content="Hugo 0.83.1" />


    <link rel="canonical" href="https://darjun.github.io/2020/01/10/godailylib/go-flags/" />





    <link rel="icon" href="https://darjun.github.io/favicon.ico" />











    <link rel="stylesheet" href="https://darjun.github.io/sass/jane.min.fa3d941d1d0e0ddc985804227feabffea55c89883eb0af34e0532a7ae9135151.css" integrity="sha256-&#43;j2UHR0ODdyYWAQif&#43;q//qVciYg&#43;sK804FMqeukTUVE=" media="screen" crossorigin="anonymous">




    <link rel="stylesheet" href="https://darjun.github.io/css/custom.css">


    <meta property="og:title" content="Go 每日一库之 go-flags" />
    <meta property="og:description" content="简介 在上一篇文章中，我们介绍了flag库。flag库是用于解析命令行选项的。但是flag有几个缺点： 不显示支持短选项。当然上一篇文章中也提到" />
    <meta property="og:type" content="article" />
    <meta property="og:url" content="https://darjun.github.io/2020/01/10/godailylib/go-flags/" /><meta property="article:section" content="post" />
    <meta property="article:published_time" content="2020-01-12T21:04:43&#43;00:00" />
    <meta property="article:modified_time" content="2020-01-12T21:04:43&#43;00:00" />

    <meta itemprop="name" content="Go 每日一库之 go-flags">
    <meta itemprop="description" content="简介 在上一篇文章中，我们介绍了flag库。flag库是用于解析命令行选项的。但是flag有几个缺点： 不显示支持短选项。当然上一篇文章中也提到"><meta itemprop="datePublished" content="2020-01-12T21:04:43&#43;00:00" />
    <meta itemprop="dateModified" content="2020-01-12T21:04:43&#43;00:00" />
    <meta itemprop="wordCount" content="3299">
    <meta itemprop="keywords" content="Go 每日一库," /><meta name="twitter:card" content="summary"/>
    <meta name="twitter:title" content="Go 每日一库之 go-flags"/>
    <meta name="twitter:description" content="简介 在上一篇文章中，我们介绍了flag库。flag库是用于解析命令行选项的。但是flag有几个缺点： 不显示支持短选项。当然上一篇文章中也提到"/>

    <!--[if lte IE 9]>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
    <![endif]-->

    <!--[if lt IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->


    <script type="application/javascript">
        var doNotTrack = false;
        if (!doNotTrack) {
            window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
            ga('create', 'UA-42862533-1', 'auto');

            ga('send', 'pageview');
        }
    </script>
    <script async src='https://www.google-analytics.com/analytics.js'></script>



</head>
<body>
<div id="mobile-navbar" class="mobile-navbar">
    <div class="mobile-header-logo">
        <a href="/" class="logo">大俊</a>
    </div>
    <div class="mobile-navbar-icon">
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>
<nav id="mobile-menu" class="mobile-menu slideout-menu">
    <ul class="mobile-menu-list">
        <li class="mobile-menu-item">



            <a class="menu-item-link" href="https://darjun.github.io/">首页</a>


        </li><li class="mobile-menu-item">



            <a class="menu-item-link" href="https://darjun.github.io/post/">归档</a>


        </li><li class="mobile-menu-item">



            <a class="menu-item-link" href="https://darjun.github.io/tags/">标签</a>


        </li><li class="mobile-menu-item">



            <a class="menu-item-link" href="https://darjun.github.io/categories/">分类</a>


        </li><li class="mobile-menu-item">



            <a class="menu-item-link" href="https://darjun.github.io/about/">关于我</a>


        </li><li class="mobile-menu-item">



            <a class="menu-item-link" href="https://github.com/darjun" rel="noopener" target="_blank">
                Github

                <i class="iconfont">
                    <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
                         xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                         width="18" height="18">
                        <path d="M623.36 272.96 473.216 423.04C467.2 429.056 467.072 438.656 472.896 444.416c0 0-6.72-6.656 1.6 1.6C496.064 467.648 528.64 500.224 528.64 500.224 534.464 506.048 544 505.856 550.016 499.904l150.08-150.144 67.328 66.432c9.024 8.96 27.456 4.544 30.4-8.96 19.968-92.608 46.656-227.52 46.656-227.52 6.848-34.496-16.192-56.704-49.92-49.92 0 0-134.656 26.816-227.328 46.784C560.32 178.048 556.352 182.272 554.752 187.136c-3.2 6.208-3.008 14.208 3.776 20.992L623.36 272.96z"></path>
                        <path d="M841.152 457.152c-30.528 0-54.784 24.512-54.784 54.656l0 274.752L237.696 786.56 237.696 237.696l206.016 0c6.656 0 10.752 0 13.248 0C487.68 237.696 512 213.184 512 182.848 512 152.32 487.36 128 456.96 128L183.04 128C153.216 128 128 152.576 128 182.848c0 3.136 0.256 6.272 0.768 9.28C128.256 195.136 128 198.272 128 201.408l0 639.488c0 0.064 0 0.192 0 0.256 0 0.128 0 0.192 0 0.32 0 30.528 24.512 54.784 54.784 54.784l646.976 0c6.592 0 9.728 0 11.712 0 28.736 0 52.928-22.976 54.464-51.968C896 843.264 896 842.304 896 841.344l0-20.352L896 561.408 896 512.128C896 481.792 871.424 457.152 841.152 457.152z"></path>
                    </svg>

                </i>
            </a>


        </li>



    </ul>
</nav>










<link rel="stylesheet" href="https://darjun.github.io/lib/photoswipe/photoswipe.min.css" />
<link rel="stylesheet" href="https://darjun.github.io/lib/photoswipe/default-skin/default-skin.min.css" />




<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <div class="pswp__bg"></div>

    <div class="pswp__scroll-wrap">

        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">

                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>


                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>







<header id="header" class="header container">
    <div class="logo-wrapper">
        <a href="/" class="logo">

            大俊

        </a>
    </div>

    <nav class="site-navbar">
        <ul id="menu" class="menu">


            <li class="menu-item">



                <a class="menu-item-link" href="https://darjun.github.io/">首页</a>




            </li>

            <li class="menu-item">



                <a class="menu-item-link" href="https://darjun.github.io/post/">归档</a>




            </li>

            <li class="menu-item">



                <a class="menu-item-link" href="https://darjun.github.io/tags/">标签</a>




            </li>

            <li class="menu-item">



                <a class="menu-item-link" href="https://darjun.github.io/categories/">分类</a>




            </li>

            <li class="menu-item">



                <a class="menu-item-link" href="https://darjun.github.io/about/">关于我</a>




            </li>

            <li class="menu-item">



                <a class="menu-item-link" href="https://github.com/darjun" rel="noopener" target="_blank">
                    Github

                    <i class="iconfont">
                        <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
                             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                             width="18" height="18">
                            <path d="M623.36 272.96 473.216 423.04C467.2 429.056 467.072 438.656 472.896 444.416c0 0-6.72-6.656 1.6 1.6C496.064 467.648 528.64 500.224 528.64 500.224 534.464 506.048 544 505.856 550.016 499.904l150.08-150.144 67.328 66.432c9.024 8.96 27.456 4.544 30.4-8.96 19.968-92.608 46.656-227.52 46.656-227.52 6.848-34.496-16.192-56.704-49.92-49.92 0 0-134.656 26.816-227.328 46.784C560.32 178.048 556.352 182.272 554.752 187.136c-3.2 6.208-3.008 14.208 3.776 20.992L623.36 272.96z"></path>
                            <path d="M841.152 457.152c-30.528 0-54.784 24.512-54.784 54.656l0 274.752L237.696 786.56 237.696 237.696l206.016 0c6.656 0 10.752 0 13.248 0C487.68 237.696 512 213.184 512 182.848 512 152.32 487.36 128 456.96 128L183.04 128C153.216 128 128 152.576 128 182.848c0 3.136 0.256 6.272 0.768 9.28C128.256 195.136 128 198.272 128 201.408l0 639.488c0 0.064 0 0.192 0 0.256 0 0.128 0 0.192 0 0.32 0 30.528 24.512 54.784 54.784 54.784l646.976 0c6.592 0 9.728 0 11.712 0 28.736 0 52.928-22.976 54.464-51.968C896 843.264 896 842.304 896 841.344l0-20.352L896 561.408 896 512.128C896 481.792 871.424 457.152 841.152 457.152z"></path>
                        </svg>

                    </i>
                </a>




            </li>






        </ul>
    </nav>

</header>

<div id="mobile-panel">
    <main id="main" class="main bg-llight">
        <div class="content-wrapper">
            <div id="content" class="content container">
                <article class="post bg-white">

                    <header class="post-header">
                        <h1 class="post-title">Go 每日一库之 go-flags</h1>

                        <div class="post-meta">
                            <time datetime="2020-01-12" class="post-time">
                                2020-01-12
                            </time>
                            <div class="post-category">
                                <a href="https://darjun.github.io/categories/go/"> Go </a>

                            </div>
                            <span class="more-meta"> 约 3299 字 </span>
                            <span class="more-meta"> 预计阅读 7 分钟 </span>



                            <span id="busuanzi_container_page_pv">
            | 阅读 <span id="busuanzi_value_page_pv"></span>
          </span>




                        </div>
                    </header>



                    <div class="post-toc" id="post-toc">
                        <h2 class="post-toc-title">文章目录</h2>
                        <div class="post-toc-content">
                            <nav id="TableOfContents">
                                <ul>
                                    <li><a href="#简介">简介</a></li>
                                    <li><a href="#快速开始">快速开始</a></li>
                                    <li><a href="#基本特性">基本特性</a>
                                        <ul>
                                            <li><a href="#支持丰富的数据类型">支持丰富的数据类型</a></li>
                                            <li><a href="#常用设置">常用设置</a></li>
                                        </ul>
                                    </li>
                                    <li><a href="#高级特性">高级特性</a>
                                        <ul>
                                            <li><a href="#选项分组">选项分组</a></li>
                                            <li><a href="#子命令">子命令</a></li>
                                        </ul>
                                    </li>
                                    <li><a href="#其他">其他</a></li>
                                    <li><a href="#参考">参考</a></li>
                                    <li><a href="#我">我</a></li>
                                </ul>
                            </nav>
                        </div>
                    </div>


                    <div class="post-content">
                        <h2 id="简介">简介</h2>
                        <p>在<a href="https://darjun.github.io/2020/01/07/godailylib/flag/">上一篇文章</a>中，我们介绍了<code>flag</code>库。<code>flag</code>库是用于解析命令行选项的。但是<code>flag</code>有几个缺点：</p>
                        <ul>
                            <li>不显示支持短选项。当然上一篇文章中也提到过可以通过将两个选项共享同一个变量迂回实现，但写起来比较繁琐；</li>
                            <li>选项变量的定义比较繁琐，每个选项都需要根据类型调用对应的<code>Type</code>或<code>TypeVar</code>函数；</li>
                            <li>默认只支持有限的数据类型，当前只有基本类型<code>bool/int/uint/string</code>和<code>time.Duration</code>；</li>
                        </ul>
                        <p>为了解决这些问题，出现了不少第三方解析命令行选项的库，今天的主角<a href="https://github.com/jessevdk/go-flags"><code>go-flags</code></a>就是其中一个。第一次看到<code>go-flags</code>库是在阅读<a href="https://github.com/sosedoff/pgweb">pgweb</a>源码的时候。</p>
                        <p><code>go-flags</code>提供了比标准库<code>flag</code>更多的选项。它利用结构标签（struct tag）和反射提供了一个方便、简洁的接口。它除了基本的功能，还提供了丰富的特性：</p>
                        <ul>
                            <li>支持短选项（-v）和长选项（&ndash;verbose）；</li>
                            <li>支持短选项合写，如<code>-aux</code>；</li>
                            <li>同一个选项可以设置多个值；</li>
                            <li>支持所有的基础类型和 map 类型，甚至是函数；</li>
                            <li>支持命名空间和选项组；</li>
                            <li>等等。</li>
                        </ul>
                        <p>上面只是粗略介绍了<code>go-flags</code>的特性，下面我们依次来介绍。</p>
                        <h2 id="快速开始">快速开始</h2>
                        <p>学习从使用开始！我们先来看看<code>go-flags</code>的基本使用。</p>
                        <p>由于是第三方库，使用前需要安装，执行下面的命令安装：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ go get github.com/jessevdk/go-flags
</code></pre></td></tr></table>
                            </div>
                        </div><p>代码中使用<code>import</code>导入该库：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">import &#34;github.com/jessevdk/go-flags&#34;
</code></pre></td></tr></table>
                            </div>
                        </div><p>完整示例代码如下：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;fmt&#34;</span>

  <span class="s">&#34;github.com/jessevdk/go-flags&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Option</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Verbose</span> <span class="p">[]</span><span class="kt">bool</span> <span class="s">`short:&#34;v&#34; long:&#34;verbose&#34; description:&#34;Show verbose debug message&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">opt</span> <span class="nx">Option</span>
  <span class="nx">flags</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">opt</span><span class="p">)</span>

  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">opt</span><span class="p">.</span><span class="nx">Verbose</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>使用<code>go-flags</code>的一般步骤：</p>
                        <ul>
                            <li>定义选项结构，在结构标签中设置选项信息。通过<code>short</code>和<code>long</code>设置短、长选项名字，<code>description</code>设置帮助信息。命令行传参时，短选项前加<code>-</code>，长选项前加<code>--</code>；</li>
                            <li>声明选项变量；</li>
                            <li>调用<code>go-flags</code>的解析方法解析。</li>
                        </ul>
                        <p>编译、运行代码（我的环境是 Win10 + Git Bash）：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ go build -o main.exe main.go
</code></pre></td></tr></table>
                            </div>
                        </div><p>短选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe -v
[true]
</code></pre></td></tr></table>
                            </div>
                        </div><p>长选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --verbose
[true]
</code></pre></td></tr></table>
                            </div>
                        </div><p>由于<code>Verbose</code>字段是切片类型，每次遇到<code>-v</code>或<code>--verbose</code>都会追加一个<code>true</code>到切片中。</p>
                        <p>多个短选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe -v -v
[true true]
</code></pre></td></tr></table>
                            </div>
                        </div><p>多个长选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --verbose --verbose
[true true]
</code></pre></td></tr></table>
                            </div>
                        </div><p>短选项 + 长选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe -v --verbose -v
[true true true]
</code></pre></td></tr></table>
                            </div>
                        </div><p>短选项合写：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe -vvv
[true true true]
</code></pre></td></tr></table>
                            </div>
                        </div><h2 id="基本特性">基本特性</h2>
                        <h3 id="支持丰富的数据类型">支持丰富的数据类型</h3>
                        <p><code>go-flags</code>相比标准库<code>flag</code>支持更丰富的数据类型：</p>
                        <ul>
                            <li>所有的基本类型（包括有符号整数<code>int/int8/int16/int32/int64</code>，无符号整数<code>uint/uint8/uint16/uint32/uint64</code>，浮点数<code>float32/float64</code>，布尔类型<code>bool</code>和字符串<code>string</code>）和<strong>它们的切片</strong>；</li>
                            <li>map 类型。只支持键为<code>string</code>，值为基础类型的 map；</li>
                            <li>函数类型。</li>
                        </ul>
                        <p>如果字段是基本类型的切片，基本解析流程与对应的基本类型是一样的。切片类型选项的不同之处在于，遇到相同的选项时，值会被追加到切片中。而非切片类型的选项，后出现的值会覆盖先出现的值。</p>
                        <p>下面来看一个示例：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;fmt&#34;</span>

  <span class="s">&#34;github.com/jessevdk/go-flags&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Option</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">IntFlag</span>         <span class="kt">int</span>             <span class="s">`short:&#34;i&#34; long:&#34;int&#34; description:&#34;int flag value&#34;`</span>
  <span class="nx">IntSlice</span>        <span class="p">[]</span><span class="kt">int</span>           <span class="s">`long:&#34;intslice&#34; description:&#34;int slice flag value&#34;`</span>
  <span class="nx">BoolFlag</span>        <span class="kt">bool</span>            <span class="s">`long:&#34;bool&#34; description:&#34;bool flag value&#34;`</span>
  <span class="nx">BoolSlice</span>       <span class="p">[]</span><span class="kt">bool</span>          <span class="s">`long:&#34;boolslice&#34; description:&#34;bool slice flag value&#34;`</span>
  <span class="nx">FloatFlag</span>       <span class="kt">float64</span>         <span class="s">`long:&#34;float&#34;, description:&#34;float64 flag value&#34;`</span>
  <span class="nx">FloatSlice</span>      <span class="p">[]</span><span class="kt">float64</span>       <span class="s">`long:&#34;floatslice&#34; description:&#34;float64 slice flag value&#34;`</span>
  <span class="nx">StringFlag</span>      <span class="kt">string</span>          <span class="s">`short:&#34;s&#34; long:&#34;string&#34; description:&#34;string flag value&#34;`</span>
  <span class="nx">StringSlice</span>     <span class="p">[]</span><span class="kt">string</span>        <span class="s">`long:&#34;strslice&#34; description:&#34;string slice flag value&#34;`</span>
  <span class="nx">PtrStringSlice</span>  <span class="p">[]</span><span class="o">*</span><span class="kt">string</span>       <span class="s">`long:&#34;pstrslice&#34; description:&#34;slice of pointer of string flag value&#34;`</span>
  <span class="nx">Call</span>            <span class="kd">func</span><span class="p">(</span><span class="kt">string</span><span class="p">)</span>    <span class="s">`long:&#34;call&#34; description:&#34;callback&#34;`</span>
  <span class="nx">IntMap</span>          <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span>  <span class="s">`long:&#34;intmap&#34; description:&#34;A map from string to int&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">opt</span> <span class="nx">Option</span>
  <span class="nx">opt</span><span class="p">.</span><span class="nx">Call</span> <span class="p">=</span> <span class="kd">func</span> <span class="p">(</span><span class="nx">value</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;in callback: &#34;</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
  <span class="p">}</span>
  
  <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">flags</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">opt</span><span class="p">)</span>
  <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Parse error:&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
    <span class="k">return</span>
  <span class="p">}</span>
  
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;int flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">IntFlag</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;int slice flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">IntSlice</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;bool flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">BoolFlag</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;bool slice flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">BoolSlice</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;float flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">FloatFlag</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;float slice flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">FloatSlice</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;string flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">StringFlag</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;string slice flag: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">StringSlice</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;slice of pointer of string flag: &#34;</span><span class="p">)</span>
  <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">opt</span><span class="p">.</span><span class="nx">PtrStringSlice</span><span class="p">);</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;\t%d: %v\n&#34;</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="o">*</span><span class="nx">opt</span><span class="p">.</span><span class="nx">PtrStringSlice</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
  <span class="p">}</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;int map: %v\n&#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">IntMap</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>基本类型和其切片比较简单，就不过多介绍了。值得留意的是基本类型指针的切片，即上面的<code>PtrStringSlice</code>字段，类型为<code>[]*string</code>。
                            由于结构中存储的是字符串指针，<code>go-flags</code>在解析过程中遇到该选项会自动创建字符串，将指针追加到切片中。</p>
                        <p>运行程序，传入<code>--pstrslice</code>选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --pstrslice test1 --pstrslice test2
slice of pointer of string flag:
    0: test1
    1: test2
</code></pre></td></tr></table>
                            </div>
                        </div><p>另外，我们可以在选项中定义函数类型。该函数的唯一要求是有一个字符串类型的参数。解析中每次遇到该选项就会以选项值为参数调用这个函数。
                            上面代码中，<code>Call</code>函数只是简单的打印传入的选项值。运行代码，传入<code>--call</code>选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --call test1 --call test2
in callback:  test1
in callback:  test2
</code></pre></td></tr></table>
                            </div>
                        </div><p>最后，<code>go-flags</code>还支持 map 类型。虽然限制键必须是<code>string</code>类型，值必须是基本类型，也能实现比较灵活的配置。
                            <code>map</code>类型的选项值中键-值通过<code>:</code>分隔，如<code>key:value</code>，可设置多个。运行代码，传入<code>--intmap</code>选项：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --intmap key1:12 --intmap key2:58
int map: map[key1:12 key2:58]
</code></pre></td></tr></table>
                            </div>
                        </div><h3 id="常用设置">常用设置</h3>
                        <p><code>go-flags</code>提供了非常多的设置选项，具体可参见<a href="https://godoc.org/github.com/jessevdk/go-flags">文档</a>。这里重点介绍两个<code>required</code>和<code>default</code>。</p>
                        <p><code>required</code>非空时，表示对应的选项必须设置值，否则解析时返回<code>ErrRequired</code>错误。</p>
                        <p><code>default</code>用于设置选项的默认值。如果已经设置了默认值，那么<code>required</code>是否设置并不影响，也就是说命令行参数中该选项可以没有。</p>
                        <p>看下面示例：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;fmt&#34;</span>
  <span class="s">&#34;log&#34;</span>

  <span class="s">&#34;github.com/jessevdk/go-flags&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Option</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Required</span>    <span class="kt">string</span>  <span class="s">`short:&#34;r&#34; long:&#34;required&#34; required:&#34;true&#34;`</span>
  <span class="nx">Default</span>     <span class="kt">string</span>  <span class="s">`short:&#34;d&#34; long:&#34;default&#34; default:&#34;default&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">opt</span> <span class="nx">Option</span>
  <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">flags</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">opt</span><span class="p">)</span>
  <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
    <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">&#34;Parse error:&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
  <span class="p">}</span>
    
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;required: &#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">Required</span><span class="p">)</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;default: &#34;</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">Default</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>运行程序，不传入<code>default</code>选项，<code>Default</code>字段取默认值，不传入<code>required</code>选项，执行报错：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe -r required-data
required:  required-data
default:  default

$ ./main.exe -d default-data -r required-data
required:  required-data
default:  default-data

$ ./main.exe
the required flag `/r, /required&#39; was not specified
2020/01/09 18:07:39 Parse error:the required flag `/r, /required&#39; was not specified
</code></pre></td></tr></table>
                            </div>
                        </div><h2 id="高级特性">高级特性</h2>
                        <h3 id="选项分组">选项分组</h3>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;fmt&#34;</span>
  <span class="s">&#34;log&#34;</span>
  <span class="s">&#34;os&#34;</span>
    
  <span class="s">&#34;github.com/jessevdk/go-flags&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Option</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Basic</span> <span class="nx">GroupBasicOption</span> <span class="s">`description:&#34;basic type&#34; group:&#34;basic&#34;`</span>
  <span class="nx">Slice</span> <span class="nx">GroupSliceOption</span> <span class="s">`description:&#34;slice of basic type&#34; group:&#34;slice&#34;`</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">GroupBasicOption</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">IntFlag</span>    <span class="kt">int</span>     <span class="s">`short:&#34;i&#34; long:&#34;intflag&#34; description:&#34;int flag&#34;`</span>
  <span class="nx">BoolFlag</span>   <span class="kt">bool</span>    <span class="s">`short:&#34;b&#34; long:&#34;boolflag&#34; description:&#34;bool flag&#34;`</span>
  <span class="nx">FloatFlag</span>  <span class="kt">float64</span> <span class="s">`short:&#34;f&#34; long:&#34;floatflag&#34; description:&#34;float flag&#34;`</span>
  <span class="nx">StringFlag</span> <span class="kt">string</span>  <span class="s">`short:&#34;s&#34; long:&#34;stringflag&#34; description:&#34;string flag&#34;`</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">GroupSliceOption</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">IntSlice</span>		<span class="kt">int</span>			<span class="s">`long:&#34;intslice&#34; description:&#34;int slice&#34;`</span>
  <span class="nx">BoolSlice</span>		<span class="kt">bool</span>		<span class="s">`long:&#34;boolslice&#34; description:&#34;bool slice&#34;`</span>
  <span class="nx">FloatSlice</span>	<span class="kt">float64</span>	<span class="s">`long:&#34;floatslice&#34; description:&#34;float slice&#34;`</span>
  <span class="nx">StringSlice</span>	<span class="kt">string</span>	<span class="s">`long:&#34;stringslice&#34; description:&#34;string slice&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">opt</span> <span class="nx">Option</span>
  <span class="nx">p</span> <span class="o">:=</span> <span class="nx">flags</span><span class="p">.</span><span class="nf">NewParser</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">opt</span><span class="p">,</span> <span class="nx">flags</span><span class="p">.</span><span class="nx">Default</span><span class="p">)</span>
  <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">p</span><span class="p">.</span><span class="nf">ParseArgs</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
  <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
    <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">&#34;Parse error:&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
  <span class="p">}</span>
    
  <span class="nx">basicGroup</span> <span class="o">:=</span> <span class="nx">p</span><span class="p">.</span><span class="nx">Command</span><span class="p">.</span><span class="nx">Group</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="s">&#34;basic&#34;</span><span class="p">)</span>
  <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">option</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">basicGroup</span><span class="p">.</span><span class="nf">Options</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;name:%s value:%v\n&#34;</span><span class="p">,</span> <span class="nx">option</span><span class="p">.</span><span class="nf">LongNameWithNamespace</span><span class="p">(),</span> <span class="nx">option</span><span class="p">.</span><span class="nf">Value</span><span class="p">())</span>
  <span class="p">}</span>
	
  <span class="nx">sliceGroup</span> <span class="o">:=</span> <span class="nx">p</span><span class="p">.</span><span class="nx">Command</span><span class="p">.</span><span class="nx">Group</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="s">&#34;slice&#34;</span><span class="p">)</span>
  <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">option</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">sliceGroup</span><span class="p">.</span><span class="nf">Options</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;name:%s value:%v\n&#34;</span><span class="p">,</span> <span class="nx">option</span><span class="p">.</span><span class="nf">LongNameWithNamespace</span><span class="p">(),</span> <span class="nx">option</span><span class="p">.</span><span class="nf">Value</span><span class="p">())</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>上面代码中我们将基本类型和它们的切片类型选项拆分到两个结构体中，这样可以使代码看起来更清晰自然，特别是在代码量很大的情况下。
                            这样做还有一个好处，我们试试用<code>--help</code>运行该程序：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe --help
Usage:
  D:\code\golang\src\github.com\darjun\go-daily-lib\go-flags\group\main.exe [OPTIONS]

basic:
  /i, /intflag:      int flag
  /b, /boolflag      bool flag
  /f, /floatflag:    float flag
  /s, /stringflag:   string flag

slice:
  /intslice:     int slice
  /boolslice     bool slice
  /floatslice:   float slice
  /stringslice:  string slice

Help Options:
  /?                 Show this help message
  /h, /help          Show this help message
</code></pre></td></tr></table>
                            </div>
                        </div><p>输出的帮助信息中，也是按照我们设定的分组显示了，便于查看。</p>
                        <h3 id="子命令">子命令</h3>
                        <p><code>go-flags</code>支持子命令。我们经常使用的 Go 和 Git 命令行程序就有大量的子命令。例如<code>go version</code>、<code>go build</code>、<code>go run</code>、<code>git status</code>、<code>git commit</code>这些命令中<code>version/build/run/status/commit</code>就是子命令。
                            使用<code>go-flags</code>定义子命令比较简单：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;errors&#34;</span>
  <span class="s">&#34;fmt&#34;</span>
  <span class="s">&#34;log&#34;</span>
  <span class="s">&#34;strconv&#34;</span>
  <span class="s">&#34;strings&#34;</span>

  <span class="s">&#34;github.com/jessevdk/go-flags&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">MathCommand</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Op</span> <span class="kt">string</span> <span class="s">`long:&#34;op&#34; description:&#34;operation to execute&#34;`</span>
  <span class="nx">Args</span> <span class="p">[]</span><span class="kt">string</span>
  <span class="nx">Result</span> <span class="kt">int64</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">this</span> <span class="o">*</span><span class="nx">MathCommand</span><span class="p">)</span> <span class="nf">Execute</span><span class="p">(</span><span class="nx">args</span> <span class="p">[]</span><span class="kt">string</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
  <span class="k">if</span> <span class="nx">this</span><span class="p">.</span><span class="nx">Op</span> <span class="o">!=</span> <span class="s">&#34;+&#34;</span> <span class="o">&amp;&amp;</span> <span class="nx">this</span><span class="p">.</span><span class="nx">Op</span> <span class="o">!=</span> <span class="s">&#34;-&#34;</span> <span class="o">&amp;&amp;</span> <span class="nx">this</span><span class="p">.</span><span class="nx">Op</span> <span class="o">!=</span> <span class="s">&#34;x&#34;</span> <span class="o">&amp;&amp;</span> <span class="nx">this</span><span class="p">.</span><span class="nx">Op</span> <span class="o">!=</span> <span class="s">&#34;/&#34;</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="s">&#34;invalid op&#34;</span><span class="p">)</span>
  <span class="p">}</span>

  <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">arg</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">args</span> <span class="p">{</span>
    <span class="nx">num</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">strconv</span><span class="p">.</span><span class="nf">ParseInt</span><span class="p">(</span><span class="nx">arg</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">64</span><span class="p">)</span>
    <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">err</span>
    <span class="p">}</span>

    <span class="nx">this</span><span class="p">.</span><span class="nx">Result</span> <span class="o">+=</span> <span class="nx">num</span>
  <span class="p">}</span>

  <span class="nx">this</span><span class="p">.</span><span class="nx">Args</span> <span class="p">=</span> <span class="nx">args</span>
  <span class="k">return</span> <span class="kc">nil</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">Option</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Math</span> <span class="nx">MathCommand</span> <span class="s">`command:&#34;math&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">opt</span> <span class="nx">Option</span>
	<span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">flags</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">opt</span><span class="p">)</span>

	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;The result of %s is %d&#34;</span><span class="p">,</span> <span class="nx">strings</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">opt</span><span class="p">.</span><span class="nx">Math</span><span class="p">.</span><span class="nx">Args</span><span class="p">,</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">Math</span><span class="p">.</span><span class="nx">Op</span><span class="p">),</span> <span class="nx">opt</span><span class="p">.</span><span class="nx">Math</span><span class="p">.</span><span class="nx">Result</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>子命令必须实现<code>go-flags</code>定义的<code>Commander</code>接口：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-golang" data-lang="golang"><span class="kd">type</span> <span class="nx">Commander</span> <span class="kd">interface</span> <span class="p">{</span>
    <span class="nf">Execute</span><span class="p">(</span><span class="nx">args</span> <span class="p">[]</span><span class="kt">string</span><span class="p">)</span> <span class="kt">error</span>
<span class="p">}</span>
</code></pre></td></tr></table>
                            </div>
                        </div><p>解析命令行时，如果遇到不是以<code>-</code>或<code>--</code>开头的参数，<code>go-flags</code>会尝试将其解释为子命令名。子命令的名字通过在结构标签中使用<code>command</code>指定。
                            子命令后面的参数都将作为子命令的参数，子命令也可以有选项。</p>
                        <p>上面代码中，我们实现了一个可以计算任意个整数的加、减、乘、除子命令<code>math</code>。</p>
                        <p>接下来看看如何使用：</p>
                        <div class="highlight"><div class="chroma">
                                <table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
                                        <td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">$ ./main.exe math --op + 1 2 3 4 5
The result of 1+2+3+4+5 is 15

$ ./main.exe math --op - 1 2 3 4 5
The result of 1-2-3-4-5 is -13

$ ./main.exe math --op x 1 2 3 4 5
The result of 1x2x3x4x5 is 120

$ ./main.exe math --op ÷ 120 2 3 4 5
The result of 120÷2÷3÷4÷5 is 1
</code></pre></td></tr></table>
                            </div>
                        </div><p>注意，不能使用乘法符号<code>*</code>和除法符号<code>/</code>，它们都不可识别。</p>
                        <h2 id="其他">其他</h2>
                        <p><code>go-flags</code>库还有很多有意思的特性，例如支持 Windows 选项格式（<code>/v</code>和<code>/verbose</code>）、从环境变量中读取默认值、从 ini 文件中读取默认设置等等。大家有兴趣可以自行去研究~</p>
                        <h2 id="参考">参考</h2>
                        <ol>
                            <li><a href="https://github.com/jessevdk/go-flags">go-flags</a>Github 仓库</li>
                            <li><a href="https://godoc.org/github.com/jessevdk/go-flags">go-flags</a>GoDoc 文档</li>
                        </ol>
                        <h2 id="我">我</h2>
                        <p><a href="https://darjun.github.io">我的博客</a></p>
                        <p>欢迎关注我的微信公众号【GoUpUp】，共同学习，一起进步~</p>
                        <p><img src="/img/wxgzh8.jpg#center" alt=""></p>

                    </div>



                    <div class="post-copyright">
                        <p class="copyright-item">
                            <span class="item-title">文章作者</span>
                            <span class="item-content">darjun</span>
                        </p>
                        <p class="copyright-item">
                            <span class="item-title">上次更新</span>
                            <span class="item-content">
      2020-01-12
      
    </span>
                        </p>

                        <p class="copyright-item">
                            <span class="item-title">许可协议</span>
                            <span class="item-content"><a rel="license noopener" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank">CC BY-NC-ND 4.0</a></span>
                        </p>
                    </div>





                    <footer class="post-footer">
                        <div class="post-tags">

                        </div>


                        <nav class="post-nav">

                            <a class="prev" href="/2020/01/13/goweb/fileserver/">

                                <i class="iconfont">
                                    <svg  class="icon" viewBox="0 0 1024 1024" version="1.1"
                                          xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                                          width="18" height="18">
                                        <path d="M691.908486 949.511495l75.369571-89.491197c10.963703-12.998035 10.285251-32.864502-1.499144-44.378743L479.499795 515.267417 757.434875 204.940602c11.338233-12.190647 11.035334-32.285311-0.638543-44.850487l-80.46666-86.564541c-11.680017-12.583596-30.356378-12.893658-41.662889-0.716314L257.233596 494.235404c-11.332093 12.183484-11.041474 32.266891 0.657986 44.844348l80.46666 86.564541c1.772366 1.910513 3.706415 3.533476 5.750981 4.877077l306.620399 321.703933C662.505829 963.726242 680.945807 962.528973 691.908486 949.511495z"></path>
                                    </svg>

                                </i>
                                <span class="prev-text nav-default">Go Web 编程之 静态文件</span>
                                <span class="prev-text nav-mobile">上一篇</span>
                            </a>

                            <a class="next" href="/2020/01/10/godailylib/flag/">
                                <span class="next-text nav-default">Go 每日一库之 flag</span>
                                <span class="prev-text nav-mobile">下一篇</span>

                                <i class="iconfont">
                                    <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
                                         xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                                         width="18" height="18">
                                        <path d="M332.091514 74.487481l-75.369571 89.491197c-10.963703 12.998035-10.285251 32.864502 1.499144 44.378743l286.278095 300.375162L266.565125 819.058374c-11.338233 12.190647-11.035334 32.285311 0.638543 44.850487l80.46666 86.564541c11.680017 12.583596 30.356378 12.893658 41.662889 0.716314l377.434212-421.426145c11.332093-12.183484 11.041474-32.266891-0.657986-44.844348l-80.46666-86.564541c-1.772366-1.910513-3.706415-3.533476-5.750981-4.877077L373.270379 71.774697C361.493148 60.273758 343.054193 61.470003 332.091514 74.487481z"></path>
                                    </svg>

                                </i>
                            </a>
                        </nav>
                    </footer>
                </article>











                <div class="post bg-white">
                    <script src="https://utteranc.es/client.js"
                            repo= "darjun/blog-comments"
                            issue-term="pathname"
                            theme="github-light"
                            crossorigin="anonymous"
                            async>
                    </script>
                </div>












            </div>
        </div>
    </main>

    <footer id="footer" class="footer">
        <div class="icon-links">


            <a href="mailto:leedarjun@gmail.com" rel="me noopener" class="iconfont"
               title="email" >
                <svg class="icon" viewBox="0 0 1451 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                     width="36" height="36">
                    <path d="M664.781909 681.472759 0 97.881301C0 3.997201 71.046997 0 71.046997 0L474.477909 0 961.649408 0 1361.641813 0C1361.641813 0 1432.688811 3.997201 1432.688811 97.881301L771.345323 681.472759C771.345323 681.472759 764.482731 685.154773 753.594283 688.65053L753.594283 688.664858C741.602731 693.493018 729.424896 695.068979 718.077952 694.839748 706.731093 695.068979 694.553173 693.493018 682.561621 688.664858L682.561621 688.65053C671.644501 685.140446 664.781909 681.472759 664.781909 681.472759L664.781909 681.472759ZM718.063616 811.603883C693.779541 811.016482 658.879232 802.205449 619.10784 767.734955 542.989056 701.759633 0 212.052267 0 212.052267L0 942.809523C0 942.809523 0 1024 83.726336 1024L682.532949 1024 753.579947 1024 1348.948139 1024C1432.688811 1024 1432.688811 942.809523 1432.688811 942.809523L1432.688811 212.052267C1432.688811 212.052267 893.138176 701.759633 817.019477 767.734955 777.248 802.205449 742.347691 811.03081 718.063616 811.603883L718.063616 811.603883Z"></path>
                </svg>

            </a>

            <a href="https://github.com/darjun" rel="me noopener" class="iconfont"
               title="github"  target="_blank"
            >
                <svg class="icon" style="" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                     width="36" height="36">
                    <path d="M512 12.672c-282.88 0-512 229.248-512 512 0 226.261333 146.688 418.133333 350.08 485.76 25.6 4.821333 34.986667-11.008 34.986667-24.618667 0-12.16-0.426667-44.373333-0.64-87.04-142.421333 30.890667-172.458667-68.693333-172.458667-68.693333C188.672 770.986667 155.008 755.2 155.008 755.2c-46.378667-31.744 3.584-31.104 3.584-31.104 51.413333 3.584 78.421333 52.736 78.421333 52.736 45.653333 78.293333 119.850667 55.68 149.12 42.581333 4.608-33.109333 17.792-55.68 32.426667-68.48-113.706667-12.8-233.216-56.832-233.216-253.013333 0-55.893333 19.84-101.546667 52.693333-137.386667-5.76-12.928-23.04-64.981333 4.48-135.509333 0 0 42.88-13.738667 140.8 52.48 40.96-11.392 84.48-17.024 128-17.28 43.52 0.256 87.04 5.888 128 17.28 97.28-66.218667 140.16-52.48 140.16-52.48 27.52 70.528 10.24 122.581333 5.12 135.509333 32.64 35.84 52.48 81.493333 52.48 137.386667 0 196.693333-119.68 240-233.6 252.586667 17.92 15.36 34.56 46.762667 34.56 94.72 0 68.522667-0.64 123.562667-0.64 140.202666 0 13.44 8.96 29.44 35.2 24.32C877.44 942.592 1024 750.592 1024 524.672c0-282.752-229.248-512-512-512"></path>
                </svg>

            </a>


            <a href="https://darjun.github.io/index.xml" rel="noopener alternate" type="application/rss&#43;xml"
               class="iconfont" title="rss" target="_blank">
                <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                     width="30" height="30">
                    <path d="M819.157333 1024C819.157333 574.592 449.408 204.8 0 204.8V0c561.706667 0 1024 462.293333 1024 1024h-204.842667zM140.416 743.04a140.8 140.8 0 0 1 140.501333 140.586667A140.928 140.928 0 0 1 140.074667 1024C62.72 1024 0 961.109333 0 883.626667s62.933333-140.544 140.416-140.586667zM678.784 1024h-199.04c0-263.210667-216.533333-479.786667-479.744-479.786667V345.173333c372.352 0 678.784 306.517333 678.784 678.826667z"></path>
                </svg>

            </a>

        </div>

        <div class="copyright">
  <span class="power-by">
    Powered by <a class="hexo-link" href="https://gohugo.io">Hugo</a>
  </span>
            <span class="division">|</span>
            <span class="theme-info">
    Theme - <a class="theme-link" href="https://github.com/xianmin/hugo-theme-jane">Jane</a>
  </span>

            <span class="copyright-year">
    &copy;
    
      2018 -
    2021
    <span class="heart">
      
      <i class="iconfont">
        <svg class="icon" viewBox="0 0 1025 1024" version="1.1"
             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
             width="14" height="14">
  <path d="M1000.1 247.9c-15.5-37.3-37.6-70.6-65.7-98.9-54.4-54.8-125.8-85-201-85-85.7 0-166 39-221.4 107.4C456.6 103 376.3 64 290.6 64c-75.1 0-146.5 30.4-201.1 85.6-28.2 28.5-50.4 61.9-65.8 99.3-16 38.8-24 79.9-23.6 122.2 0.7 91.7 40.1 177.2 108.1 234.8 3.1 2.6 6 5.1 8.9 7.8 14.9 13.4 58 52.8 112.6 102.7 93.5 85.5 209.9 191.9 257.5 234.2 7 6.1 15.8 9.5 24.9 9.5 9.2 0 18.1-3.4 24.9-9.5 34.5-30.7 105.8-95.9 181.4-165 74.2-67.8 150.9-138 195.8-178.2 69.5-57.9 109.6-144.4 109.9-237.3 0.1-42.5-8-83.6-24-122.2z"
        fill="#8a8a8a"></path>
</svg>

      </i>
    </span><span class="author">
        大俊
        
      </span></span>



            <span id="busuanzi_container">
      访客数/访问量：<span id="busuanzi_value_site_uv"></span>/<span id="busuanzi_value_site_pv"></span>
    </span>



        </div>

    </footer>

    <div class="back-to-top" id="back-to-top">
        <i class="iconfont">

            <svg class="icon" viewBox="0 0 1024 1024" version="1.1"
                 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                 width="35" height="35">
                <path d="M510.866688 227.694839 95.449397 629.218702l235.761562 0-2.057869 328.796468 362.40389 0L691.55698 628.188232l241.942331-3.089361L510.866688 227.694839zM63.840492 63.962777l894.052392 0 0 131.813095L63.840492 195.775872 63.840492 63.962777 63.840492 63.962777zM63.840492 63.962777"></path>
            </svg>

        </i>
    </div>
</div>

<script type="text/javascript" src="/lib/jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="/lib/slideout/slideout-1.0.1.min.js"></script>




<script type="text/javascript" src="/js/main.638251f4230630f0335d8c6748e53a96f94b72670920b60c09a56fdc8bece214.js" integrity="sha256-Y4JR9CMGMPAzXYxnSOU6lvlLcmcJILYMCaVv3Ivs4hQ=" crossorigin="anonymous"></script>













<script type="text/javascript" src="/js/load-photoswipe.js"></script>
<script type="text/javascript" src="/lib/photoswipe/photoswipe.min.js"></script>
<script type="text/javascript" src="/lib/photoswipe/photoswipe-ui-default.min.js"></script>





<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>












</body>
</html>
